// ==UserScript==
// @name         一键下载图片
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.bilibili.com/read/*
// @match        https://www.zhihu.com/question/*
// @match        https://zhuanlan.zhihu.com/p/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=firefoxchina.cn
// @grant        none
// ==/UserScript==
const bubbleClick = new MouseEvent('click', {bubbles: true})
let htmlText = `
<div id="images-download-script" draggable="true">
  <input id="filename-prefix" placeholder="自定义文件名前缀">
  <button id="zhihu-checkbox">
    选择要下载的图片
  </button>
  <button id="do-images-downLoad">
    下载所有图片 
  </button>
</div>
<style>
  #images-download-script{
    width: 200px;
    height: 100px;
    border-radius: 10px;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: space-around;
    position: fixed;
    right: 5px;
    top: 100px;
    z-index: 500;
    background-color: rgb(198, 194, 194);
  }
  #images-download-script > input{
    border: 1px gray;
    font-size: 13px;
    color: black;
  }
  #images-download-script > button{
    font-size: 13px;
    color: red;
    margin: 0 20px;
  }
</style>
`
// 立即执行函数前面必须加分号
// 脚本执行入口
;(function(){
  initDom()
  handleEvent()
})();


// 获取要下载的图片链接
function getImgs(){
  if(/https:\/\/www.bilibili.com\/read\//.test(window.location.href)){
    return document.querySelectorAll('#article-content img:not(img[class*="cut-off"])')
  }
  // 知乎
  else if(/https:\/\/.*zhihu.com/.test(window.location.href)){
    // 直接得到的img是预览的，清晰度低
    let rawImgs = []
    // 知乎回答
    if(/https:\/\/www.zhihu.com\/question/.test(window.location.href)){
      let answerContents = document.querySelectorAll('.RichContent-inner')
      let checkboxes = document.querySelectorAll('.ans-check')
      if(checkboxes.length == 0){
        return []
      }
      for(let cb of checkboxes){
        if(!cb.checked){
          answerContents[parseInt(cb.value)].remove()
        }
      }
      rawImgs = document.querySelectorAll('.RichContent-inner img')
    }
    // 知乎专栏
    else if(/https:\/\/zhuanlan.zhihu.com\/p/.test(window.location.href)){
      let allImgs = document.querySelectorAll('article img')
      for(let img of allImgs){
        console.log(img.src)
        if(/com.+?_/.test(img.src)){
          rawImgs.push(img)
        }
      }
    }
    // 把预览的rawImg转换为原画质的img
    let imgs = []
    for(let rawImg of rawImgs){
      let src = rawImg.src
      let egx = /com.+?_/
      let matchResult = src.match(egx)
      if(!matchResult){
        continue;
      }
      let id = matchResult[0].substring(4)
      src = src.substring(0, src.indexOf('.com/') + 5) + id + 'r.jpg'
      let img = new Image()
      img.src = src
      imgs.push(img)
    }
    return imgs
  }
  return document.querySelectorAll('img')
}


// 为脚本的dom元素绑定事件
function handleEvent(){
  let button = document.querySelector('#do-images-downLoad')
  let inp = document.querySelector('#filename-prefix')

  // 点击，获取图片链接，然后对图片进行下载
  button.addEventListener('click', async () => {
    button.disabled = 'true'
    let imgs = getImgs()
    let idx = 1001;
    let prefix = inp.value || timeFormat(new Date())
    for(let img of imgs){
      let src = img.src
      if(src.includes('?')){
        src = src.substring(0, src.indexOf('?'))
      }
      else if(src.includes('@')){
        src = src.substring(0, src.indexOf('@'))
      }
      try{
        await downloadIamge(src, prefix + '-' + idx.toString().substring(1))
      }
      catch(e){
        console.log(e + ' error')
      }
      idx++
    }
    button.removeAttribute('disabled')
  })

  // 如果是知乎回答页面，则添加显示选择框按钮的
  if(/https:\/\/www.zhihu.com\/question/.test(window.location.href)){
    document.querySelector('#zhihu-checkbox').onclick = initZhiHuCheckbox
  }

}

// 初始化脚本dom
function initDom(){
  let div = document.createElement('div')
  div.innerHTML = htmlText
  document.querySelector('body').append(div)
  document.querySelector('#zhihu-checkbox').style.display = 'none'
  if(/https:\/\/www.zhihu.com\/question/.test(window.location.href)){
    let answerContents = document.querySelectorAll('.RichContent-inner')
    document.querySelector('#zhihu-checkbox').style.display = 'inline'
  }
}

// 抄的，根据src下载图片，第一个参数为src，第二个参数为文件名
function downloadIamge(src, name) {
  return new Promise((resolve, reject) => {
    var image = new Image()
    // 解决跨域 Canvas 污染问题
    image.setAttribute('crossOrigin', 'anonymous')
    image.onerror = () => {
      reject(name)
    }
    image.onload = function () {
        var canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        
        var context = canvas.getContext('2d')
        context.drawImage(image, 0, 0, image.width, image.height)
        var url = canvas.toDataURL('image/png')

        // 生成一个a元素
        var a = document.createElement('a')
        // 创建一个单击事件
        var event = new MouseEvent('click')

        // 将a的download属性设置为我们想要下载的图片名称，若name不存在则使用‘下载图片名称’作为默认名称
        a.download = name || '下载图片名称'
        // 将生成的URL设置为a.href属性
        a.href = url

        // 触发a的单击事件
        a.dispatchEvent(event)
        resolve()
    }
    image.src = src
  })
}

// 格式化时间
function timeFormat(date){
  let yyyy = date.getFullYear().toString()
  let mm = (date.getMonth() + 1).toString().padStart(2, '0')
  let dd = date.getDay().toString().padStart(2, '0')
  let hh = date.getHours().toString().padStart(2, '0')
  let ss = date.getMinutes().toString().padStart(2, '0')
  return yyyy + mm + dd + hh + ss
}

// 为每个知乎回答生成选择框
function initZhiHuCheckbox(){
  let answerContents = document.querySelectorAll('.RichContent-inner')
  console.log(answerContents)
  for(let i = 0; i < answerContents.length; i++){
    let checkboxString = `<input type="checkbox" class="ans-check" value="${i}">下载当前回答内图片`
    let label = document.createElement('label')
    label.innerHTML = checkboxString
    label.style.color = 'red'
    if(answerContents[i].childNodes[0].childNodes[0].className == `ans-check`){
      answerContents[i].childNodes[0].remove()
    }
    answerContents[i].insertBefore(label, answerContents[i].childNodes[0])
  }
}
